﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

namespace MemoDb
{
    public class TypeStorage : ITypeMapping
    {
        private readonly IDictionary<object, object> objects = new Dictionary<object, object>();

        PropertyInfo ITypeMapping.Id
        {
            get { return IdMapper.Property; }
        }

        IEnumerable<Cascade> ITypeMapping.CascadeInserts
        {
            get { return cascadeInserts; }
        }

        IEnumerable<Cascade> ITypeMapping.CascadeDeleteOrphans
        {
            get { return cascadeDeleteOrphans; }
        }

        private readonly IEnumerable<Cascade> cascadeInserts;
        private readonly IEnumerable<Cascade> cascadeDeleteOrphans;

        public TypeStorage(Type type, IdMapper id, IEnumerable<Cascade> cascadeInserts, IEnumerable<Cascade> cascadeDeleteOrphans)
        {
            IdMapper = id ?? IdMapper.Assigned(type, "Id");
            IdMapper.TypeStorage = this;
            Type = type;
            this.cascadeInserts = cascadeInserts;
            this.cascadeDeleteOrphans = cascadeDeleteOrphans;
        }

        public Type Type { get; private set; }
        

        public IEnumerable Items
        {
            get { return objects.Values; }
        }

        public IdMapper IdMapper { get; private set; }

        public void Insert(object source)
        {
            objects.Add(GetId(source), source);
        }

        public void Update(object source)
        {
            var id = GetId(source);
            objects[id] = source;
        }

        public void Delete(object source)
        {
            var id = GetId(source);
            objects.Remove(id);
        }

        public object GetById(object id)
        {
            object obj;
            objects.TryGetValue(id, out obj);
            return obj;
        }

        private object GetId(object source)
        {
            return IdMapper.GetId(source);
        }

        public bool Contains(object id)
        {
            return objects.ContainsKey(id);
        }

        public Cascade CascadeInsert(PropertyInfo property)
        {
            return cascadeInserts.SingleOrDefault(x => x.Reference == property);
        }
        public Cascade CascadeDeleteOrphans(PropertyInfo property)
        {
            return cascadeDeleteOrphans.SingleOrDefault(x => x.Reference == property);
        }

        public bool IsNew(object obj)
        {
            return IdMapper.IsNew(obj);
        }
    }
}